package com.shan.ai.combo.impl;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Stroke;
import java.awt.Toolkit;
import java.awt.geom.GeneralPath;
import java.awt.image.BufferedImage;
import java.awt.image.CropImageFilter;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;

import com.shan.ai.combo.IComboConstant;

public class ScreenParser implements IComboConstant {

//    private static int FIRST_X = 50;
//    private static int FIRST_Y = 590;
    private static int FIRST_X = 90;
    private static int FIRST_Y = 940;
    private static int WIDTH = 180;
    private static int HEIGHT = 180;

    private static int RED = 180;
    private static int GREEN = 285;
    private static int DRAK = 305;
    private static int HEART = 410;
    private static int LIGHT = 230;
    private static int WATER = 220;

    private static int[] COLORS = { RED, WATER, GREEN, LIGHT, DRAK, HEART };

    public static String screenCapPath = "c:\\test\\ss.png";

    public static void main(String[] args) {
//          pressLong(1000);
        
        //屏幕截图
        srceenCap(screenCapPath);
        
        //解析截图
        BeadType[][]  screen = parseScreenCap(new File(screenCapPath));
        
        //打印解析结果
        printBorad(screen);
        
       
        
//        int distanct = parseScreenCap2();
//        pressLong(distanct * 1000 / 340 - 150);
//
//        List<Point> stepList = new BeadList();
//        
//        stepList.add(new Point(0,0));
//        stepList.add(new Point(0,5));
//        stepList.add(new Point(4,5));
//        
//        drawLinesOnDevice(stepList);
    }
    
    /**
     * 屏幕截屏
     * @param filePath
     * @return
     */
    public static boolean srceenCap(String filePath) {
        long t1 = System.currentTimeMillis();
        try {
            Process process = Runtime.getRuntime().exec("adb shell am startservice -a com.shan.combo.assist.service.clear");
            process.waitFor();
            process = Runtime.getRuntime().exec("adb shell screencap /sdcard/ss.png");
            process.waitFor();
            process = Runtime.getRuntime().exec("adb pull /sdcard/ss.png " + filePath);
            process.waitFor();
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long t2 = System.currentTimeMillis();
        
        System.out.println("ScreenCap:" + (t2-t1));

        return true;
    }
    
    /**
     * 解析截图文件
     * @param screenCapFile
     * @return 分析的矩阵
     */
//    public static BeadType[][] parseScreenCap(File screenCapFile) {
//        
//        BufferedImage img = null;
//        try {
//            img = ImageIO.read(screenCapFile);
//        } catch (Exception e) {
//            e.printStackTrace();
//            return null;
//        }
//
//        int[] rgb = new int[3];
//
//        // int width = img.getWidth();
//        // int height = img.getHeight();
//        // int minx = img.getMinX();
//        // int miny = img.getMinY();
//        // System.out.println("width=" + width + ",height=" + height + ".");
//        // System.out.println("minx=" + minx + ",miniy=" + miny + ".");
//
//        BeadType[][] beads = new BeadType[MAX_ROW][MAX_COLUMN];
//
//        for (int x = 0; x < 6; x++) {
//            for (int y = 0; y < 5; y++) {
//                int pixel = img.getRGB(FIRST_X + WIDTH * x, FIRST_Y + HEIGHT * y);
//                
//                rgb[0] = (pixel & 0xff0000) >> 16;
//                rgb[1] = (pixel & 0xff00) >> 8;
//                rgb[2] = (pixel & 0xff);
//               
//                beads[y][x] = computeColors2(rgb);
//                
//                System.out.println(x+"," + y+":("+rgb[0]+","+rgb[1]+","+rgb[2]+")" + beads[y][x] + "==(" + (FIRST_X + WIDTH * x )+ "," + (FIRST_Y + HEIGHT * y) + ")" );
//            }
//        }
//
//        return beads;
//    }
    
    /**
     * 解析截图文件
     * @param screenCapFile
     * @return 分析的矩阵
     */
    public static BeadType[][] parseScreenCap(File screenCapFile) {
        long t1 = System.currentTimeMillis();
        BufferedImage img = null;
        try {
            img = ImageIO.read(screenCapFile);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

        int[] rgb = new int[3];

        // int width = img.getWidth();
        // int height = img.getHeight();
        // int minx = img.getMinX();
        // int miny = img.getMinY();
        // System.out.println("width=" + width + ",height=" + height + ".");
        // System.out.println("minx=" + minx + ",miniy=" + miny + ".");

        BeadType[][] beads = new BeadType[MAX_ROW][MAX_COLUMN];
        
        //点阵范围
        int delta = 40;

        for (int x = 0; x < 6; x++) {
            for (int y = 0; y < 5; y++) {
                //初始化RGB
                rgb[0] = 0;
                rgb[1] = 0;
                rgb[2] = 0;
                
//                ImageFilter cropFilter = new CropImageFilter(FIRST_X + WIDTH * x - delta, FIRST_Y + HEIGHT * y - delta, 2 * delta, 2 * delta);
//                Image partImage = Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(img.getSource(), cropFilter));
//
//                BufferedImage bi = new BufferedImage(delta, delta, BufferedImage.TYPE_INT_RGB );
                
                
                // 取点周围10像素的点阵
                for (int di = -delta; di < delta; di++) {
                    for (int dj = -delta; dj < delta; dj++) {
                        int pixel = img.getRGB(FIRST_X + WIDTH * x +di, FIRST_Y + HEIGHT * y +dj);
                        //累加周围所有点的RGB
                        rgb[0] += (pixel & 0xff0000) >> 16;
                        rgb[1] += (pixel & 0xff00) >> 8;
                        rgb[2] += (pixel & 0xff);
                    }
                }
                
                rgb[0] = rgb[0]/(4*delta*delta);
                rgb[1] = rgb[1]/(4*delta*delta);
                rgb[2] = rgb[2]/(4*delta*delta);

                beads[y][x] = computeColors3(rgb);

//                System.out.println(x + "," + y + ":(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + ")" + beads[y][x] + "==(" + (FIRST_X + WIDTH * x) + ","
//                        + (FIRST_Y + HEIGHT * y) + ")");
            }
        }

        long t2 = System.currentTimeMillis();
        System.out.println("parseScreenCap:" + (t2-t1));
        return beads;
    }



    private static BeadType computeColor(int color) {
        int minDiff = 1000;
        BeadType type = BeadType.none;
        for (int i = 0; i < COLORS.length; i++) {
            int diff = Math.abs(color - COLORS[i]);
            if (minDiff > diff) {
                minDiff = diff;
                type = BeadType.values()[i];
            }
        }
        return type;
    }

    /**
     * for 神魔之塔
     * @param rgb
     * @return
     */
    private static BeadType computeColors(int[] rgb) {

        if (rgb[0] > 245 && rgb[1] < 100 && rgb[2] < 100) {
            return BeadType.fire;
        } else if ((Math.abs(rgb[0] - 50) < 10) && (Math.abs(rgb[1] - 110) < 10) && (Math.abs(rgb[2] - 15) < 10)) {
            return BeadType.wood;
        } else if ((Math.abs(rgb[0] - 150) < 10) && (Math.abs(rgb[1] - 5) < 10) && (Math.abs(rgb[2] - 150) <= 10)) {
            return BeadType.dark;
        } else if ((Math.abs(rgb[0] - 220) < 10) && (Math.abs(rgb[1] - 40) < 10) && (Math.abs(rgb[2] - 130) < 10)) {
            return BeadType.heart;
        } else if ((Math.abs(rgb[0] - 240) < 10) && (Math.abs(rgb[1] - 200) < 10) && (Math.abs(rgb[2] - 0) < 10)) {
            return BeadType.light;
        } else if ((Math.abs(rgb[0] - 50) < 10) && (Math.abs(rgb[1] - 162) < 10) && (Math.abs(rgb[2] - 205) < 10)) {
            return BeadType.water;
        } else if (rgb[0] < 100 && rgb[2] > 150) {
            return BeadType.water;
        } else if (Math.abs(rgb[0] - 140) < 60 && Math.abs(rgb[1] - 250) < 10 && Math.abs(rgb[2] - 80) < 35) {
            return BeadType.wood;// 强化绿色
        } else if (rgb[0] > 245 && rgb[1] > 200 && rgb[2] > 200) {
            return BeadType.dark; // 强化暗
        } else if (rgb[0] > 245 && rgb[1] > 200 && rgb[2] < 100) {
            return BeadType.light; // 强化光
        } else if (rgb[0] > 245 && Math.abs(rgb[1] - 155) < 10 && rgb[2] < 100) {
            return BeadType.fire;// 强化火
        } else if (rgb[0] > 245 && Math.abs(rgb[1] - 180) < 10 && Math.abs(rgb[2] - 200) < 20) {
            return BeadType.heart; // 强化光
        }

        return BeadType.unknown;
    }
    
    /**
     * for 智龙迷城
     * @param rgb
     * @return
     */
    private static BeadType computeColors2(int[] rgb) {

        if ( rgb[2] > 250) {
            return BeadType.water; 
        }else if ( rgb[0] > 250  && rgb[1] > 230) {
            return BeadType.light; 
        }else if ( Math.abs(rgb[0] - 240) < 20 && Math.abs(rgb[1] - 150) < 50 && rgb[2] < 150) {
            return BeadType.fire;
        }else if ( Math.abs(rgb[0] - 240) < 20 && Math.abs(rgb[1] - 80) < 30 && rgb[2] < 150) {
            return BeadType.fire;
        }else if ( Math.abs(rgb[0] - 220) < 20  && Math.abs(rgb[1] - 35) < 20 && Math.abs(rgb[2] - 140) < 20) {
            return BeadType.heart; 
        }else if ( Math.abs(rgb[0] - 250) < 20  && Math.abs(rgb[1] - 85) < 20 && Math.abs(rgb[2] - 190) < 20) {
            return BeadType.heart; 
        }else if (rgb[0] < 200  && Math.abs(rgb[1] - 200) < 20 && rgb[2] < 200 ) {
            return BeadType.wood;
        }else if (rgb[0] < 200  && Math.abs(rgb[1] - 240) < 20 && rgb[2] < 200 ) {
            return BeadType.wood; 
        }else if ( Math.abs(rgb[0] - 10) < 10  && rgb[1] < 10 && Math.abs(rgb[2] - 60) < 20) {
            return BeadType.dark; 
        }else if ( Math.abs(rgb[0] - 220) < 40  && Math.abs(rgb[1] - 130) < 50 && Math.abs(rgb[2] - 200) < 40) {
            return BeadType.dark; 
        }else if ( Math.abs(rgb[0] - 150) < 25  && Math.abs(rgb[1] - 100) < 30 && Math.abs(rgb[2] - 170) < 20) {
            return BeadType.dark; 
        }else if ( Math.abs(rgb[0] - 70) < 10  && Math.abs(rgb[1] - 30) < 10 && Math.abs(rgb[2] - 100) < 20) {
            return BeadType.dark; 
        }else if ( Math.abs(rgb[0] - 120) < 20  && Math.abs(rgb[1] - 60) < 20 && Math.abs(rgb[2] - 150) < 20) {
            return BeadType.dark; 
        }

        return BeadType.unknown;
    }
    
    /**
     * for 智龙迷城
     * @param rgb
     * @return
     */
    private static BeadType computeColors3(int[] rgb) {

        if ( Math.abs(rgb[0] - 85) < 15 && Math.abs(rgb[1] - 180) < 15 && Math.abs(rgb[2] - 115) < 10){
            return BeadType.wood;
        }else if ( Math.abs(rgb[0] - 240) < 10 && Math.abs(rgb[1] - 110) < 10 && Math.abs(rgb[2] - 85) < 10){
            return BeadType.fire;
        }else if ( Math.abs(rgb[0] - 85) < 10 && Math.abs(rgb[1] - 170) < 10 && Math.abs(rgb[2] - 225) < 10){
            return BeadType.water;
        }else if ( Math.abs(rgb[0] - 230) < 10 && Math.abs(rgb[1] - 220) < 10 && Math.abs(rgb[2] - 90) < 10){
            return BeadType.light;
        }else if ( Math.abs(rgb[0] - 160) < 15 && Math.abs(rgb[1] - 85) < 10 && Math.abs(rgb[2] - 175) < 10){
            return BeadType.dark;
        }else if ( Math.abs(rgb[0] - 235) < 10 && Math.abs(rgb[1] - 85) < 15 && Math.abs(rgb[2] - 175) < 15){
            return BeadType.heart;
        }else if ( Math.abs(rgb[0] - 0) < 10 && Math.abs(rgb[1] - 0) < 15 && Math.abs(rgb[2] - 0) < 15){
            return BeadType.water;
        }

        return BeadType.dark;
    }



    public static void pressPoint(int x, int y) {
        
        try {
            long t1 = System.currentTimeMillis();
            Process process;
            process = Runtime.getRuntime().exec("adb shell sendevent /dev/input/event10 3 58 1000");
//            process.waitFor();
            process = Runtime.getRuntime().exec("adb shell sendevent /dev/input/event10 3 53 " + x);
//            process.waitFor();
            process = Runtime.getRuntime().exec("adb shell sendevent /dev/input/event10 3 54 " + y);
//            process.waitFor();
            process = Runtime.getRuntime().exec("adb shell sendevent /dev/input/event10 3 57 0");
            System.out.println("start waitFor1:" + (System.currentTimeMillis()-t1));
//            process.waitFor();
//            Thread.sleep(50);
            System.out.println("end waitFor1:" + (System.currentTimeMillis()-t1));
            process = Runtime.getRuntime().exec("adb shell sendevent /dev/input/event10 0 2 0");
//            process.waitFor();
            process = Runtime.getRuntime().exec("adb shell sendevent /dev/input/event10 0 0 0");
            System.out.println("start waitFor2:" + (System.currentTimeMillis()-t1));
            process.waitFor();
//            Thread.sleep(30);
            System.out.println("end waitFor2:" + (System.currentTimeMillis()-t1));
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    
    public static void pressLine(Point from, Point to) {
//        for (int i = 1; i <= 10; i++) {
//            pressPoint(from.x + (to.x-from.x)/10*i,from.y + (to.y - from.y)/10*i);
//        }
        
        pressPoint(from.x,from.y);
        pressPoint(to.x,to.y);
      
    }


    public static void pressLong(int time) {
        System.out.println("time:" + time);
        try {
            System.out.println("Press");
            long currTime = 0;
            Process process;

            process = Runtime.getRuntime().exec("adb shell sendevent /dev/input/event10 3 58 10");
            process.waitFor();
            process = Runtime.getRuntime().exec("adb shell sendevent /dev/input/event10 3 53 350");
            process.waitFor();
            process = Runtime.getRuntime().exec("adb shell sendevent /dev/input/event10 3 54 900");
            process.waitFor();
            process = Runtime.getRuntime().exec("adb shell sendevent /dev/input/event10 3 57 0");
            process.waitFor();
            process = Runtime.getRuntime().exec("adb shell sendevent /dev/input/event10 0 2 0");
            process.waitFor();
            process = Runtime.getRuntime().exec("adb shell sendevent /dev/input/event10 0 0 0");
            process.waitFor();
            Thread.sleep(time-150);
            currTime += 20;

            System.out.println("Press !");

            for (int i = 0; i < 1; i++) {

                process = Runtime.getRuntime().exec("adb shell sendevent /dev/input/event10 0 2 0");
                process.waitFor();
                process = Runtime.getRuntime().exec("adb shell sendevent /dev/input/event10 0 0 0");
                process.waitFor();
            }

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public static int parseScreenCap2() {
        File f = new File(screenCapPath);
        BufferedImage img = null;
        try {
            img = ImageIO.read(f);
        } catch (Exception e) {
            e.printStackTrace();
            return -1;
        }

        int[] rgb = new int[3];

        int last = -1;

        ArrayList<Integer> pointList = new ArrayList<Integer>();
        boolean bStart = false;
        for (int x = 10; x < 700; x++) {
            int pixel = img.getRGB(x, 1000);
            // System.out.println(pixel);
            rgb[0] = (pixel & 0xff0000) >> 16;
            rgb[1] = (pixel & 0xff00) >> 8;
            rgb[2] = (pixel & 0xff);

            if (rgb[0] == 0) {
                bStart = true;
            }

            if (!bStart) {
                continue;
            }

            if (Math.abs(rgb[0] - last) > 10) {
                System.out.println(x + "=" + rgb[0] + "," + rgb[1] + "," + rgb[2]);
                pointList.add(x);
            }

            last = rgb[0];
        }

        System.out.println(pointList.get(1) - pointList.get(0) + (pointList.get(2) - pointList.get(1)) / 2);

        return pointList.get(1) - pointList.get(0) + (pointList.get(2) - pointList.get(1)) / 2;
    }

    public static void drawLinesOnDevice(List<Point> stepList) {
        StringBuffer sb = new StringBuffer();
        sb.append("adb shell am startservice -a com.shan.combo.assist.service.draw --eia location ");
        for (int i = 0; i < stepList.size(); i++) {
            Point p = stepList.get(i);
            sb.append(p.x + "," + p.y);
            if (i < stepList.size() - 1) {
                sb.append(",");
            }
        }
        System.out.println("DrawLines:" + sb.toString());
        try {
            Process process = Runtime.getRuntime().exec(sb.toString());
            process.waitFor();

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
    
    public static void untouch(){
        try {
            Process process ;
            process = Runtime.getRuntime().exec("adb shell sendevent /dev/input/event10 0 2 0");
//            process.waitFor();
            process = Runtime.getRuntime().exec("adb shell sendevent /dev/input/event10 0 0 0");
//            process.waitFor();
            process = Runtime.getRuntime().exec("adb shell sendevent /dev/input/event10 0 2 0");
//            process.waitFor();
            process = Runtime.getRuntime().exec("adb shell sendevent /dev/input/event10 0 0 0");
            process.waitFor();
        } catch (Exception e) {
           e.printStackTrace();
        }
       
    }

    public static void touchLines(List<Point> stepList) {
        Point fromPoint = stepList.get(0);

        for (int i = 1; i < stepList.size(); i++) {
            Point toPoint = stepList.get(i);
           

            if (i < stepList.size() - 1) {
                Point toNextPoint = stepList.get(i+1);
                if(toNextPoint.x != fromPoint.x && toNextPoint.y != fromPoint.y){
                    pressLine(new Point(FIRST_X + WIDTH * fromPoint.y, FIRST_Y + HEIGHT * fromPoint.x), new Point(FIRST_X + WIDTH * toPoint.y, FIRST_Y + HEIGHT
                            * toPoint.x));
                }else{
                    continue;
                }
               
            } else {
                pressLine(new Point(FIRST_X + WIDTH * fromPoint.y, FIRST_Y + HEIGHT * fromPoint.x), new Point(FIRST_X + WIDTH * toPoint.y, FIRST_Y + HEIGHT
                        * toPoint.x));
            }
            
            fromPoint = toPoint;

            
        }
        
        untouch();
    }

    public static void drawLines(List<Point> stepList, String imgName) {
        File f = new File(screenCapPath);
        BufferedImage img = null;
        try {
            img = ImageIO.read(f);
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }

        Graphics2D g = (Graphics2D) img.getGraphics();
        Stroke stroke = new BasicStroke(4.0f);
        g.setColor(Color.BLACK);
        g.setStroke(stroke);

        Point fromPoint = stepList.get(0);

        for (int i = 1; i < stepList.size(); i++) {
            Point toPoint = stepList.get(i);

            if (i < stepList.size() - 1) {
                g.drawLine(FIRST_X + WIDTH * fromPoint.y, FIRST_Y + HEIGHT * fromPoint.x, FIRST_X + WIDTH * toPoint.y, FIRST_Y + HEIGHT * toPoint.x);
            } else {
                drawAL(FIRST_X + WIDTH * fromPoint.y, FIRST_Y + HEIGHT * fromPoint.x, FIRST_X + WIDTH * toPoint.y, FIRST_Y + HEIGHT * toPoint.x, g);
            }

            fromPoint = toPoint;
        }

        g.dispose();

        img.flush();

        try {
            ImageIO.write(img, "png", new File("C:\\test\\" + imgName + ".png"));
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private static void drawAL(int sx, int sy, int ex, int ey, Graphics2D g2) {

        double H = 20; // 箭头高度
        double L = 12; // 底边的一半
        int x3 = 0;
        int y3 = 0;
        int x4 = 0;
        int y4 = 0;
        double awrad = Math.atan(L / H); // 箭头角度
        double arraow_len = Math.sqrt(L * L + H * H); // 箭头的长度
        double[] arrXY_1 = rotateVec(ex - sx, ey - sy, awrad, true, arraow_len);
        double[] arrXY_2 = rotateVec(ex - sx, ey - sy, -awrad, true, arraow_len);
        double x_3 = ex - arrXY_1[0]; // (x3,y3)是第一端点
        double y_3 = ey - arrXY_1[1];
        double x_4 = ex - arrXY_2[0]; // (x4,y4)是第二端点
        double y_4 = ey - arrXY_2[1];

        Double X3 = new Double(x_3);
        x3 = X3.intValue();
        Double Y3 = new Double(y_3);
        y3 = Y3.intValue();
        Double X4 = new Double(x_4);
        x4 = X4.intValue();
        Double Y4 = new Double(y_4);
        y4 = Y4.intValue();
        // 画线
        g2.drawLine(sx, sy, ex, ey);
        //
        GeneralPath triangle = new GeneralPath();
        triangle.moveTo(ex, ey);
        triangle.lineTo(x3, y3);
        triangle.lineTo(x4, y4);
        triangle.closePath();
        // 实心箭头
        g2.fill(triangle);
        // 非实心箭头
        // g2.draw(triangle);

    }

    // 计算
    private static double[] rotateVec(int px, int py, double ang, boolean isChLen, double newLen) {

        double[] mathstr = new double[2];
        // 矢量旋转函数，参数含义分别是x分量、y分量、旋转角、是否改变长度、新长度
        double vx = px * Math.cos(ang) - py * Math.sin(ang);
        double vy = px * Math.sin(ang) + py * Math.cos(ang);
        if (isChLen) {
            double d = Math.sqrt(vx * vx + vy * vy);
            vx = vx / d * newLen;
            vy = vy / d * newLen;
            mathstr[0] = vx;
            mathstr[1] = vy;
        }
        return mathstr;
    }
    
    public static void printBorad(BeadType[][] beads) {
        // System.out.println("Board:");
        for (int i = 0; i < MAX_ROW; i++) {
            for (int j = 0; j < MAX_COLUMN; j++) {
                System.out.print(String.format("%10s", beads[i][j] + "(" + j + "," + i+ ")") + " ");
                // System.out.print(String.format("%10s", beads[i][j].ordinal()
                // + "(" + i + "," + j + ")") + " ");
            }
            System.out.println();
        }
    }




}
